﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xml;

namespace LogoFX.Infra.Util
{
    public class ViewSelector : DataTemplateSelector
    {
        private const string MAIN_CONTEXT = "Main";
        private static DataTemplate EmptyTemplate;
        static ViewSelector()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' >\n");
            builder.Append("</DataTemplate>");
            try
            {
                using (TextReader textReader = new StringReader(builder.ToString()))
                using (XmlReader xmlReader = new XmlTextReader(textReader))
                {
                    EmptyTemplate = XamlReader.Load(xmlReader) as DataTemplate;
                }
            }
            catch (Exception e)
            {
                Trace.Write("Unable to create empty DataTemplate");
            }
        }

        public ViewSelector(string context)
        {
            _context = context;
        }
        public string Context
        {
            get { return _context; }
        }
        #region Context attached property

        public static string GetContext(DependencyObject obj)
        {
            return (string)obj.GetValue(ContextProperty);
        }

        public static void SetContext(DependencyObject obj, string value)
        {
            obj.SetValue(ContextProperty, value);
        }

        public static readonly DependencyProperty ContextProperty =
            DependencyProperty.RegisterAttached("Context", typeof(string), typeof(ViewSelector),
                                                new PropertyMetadata(default(string), OnContextChanged));

        private readonly string _context;

        private static void OnContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

            ViewSelector viewSelector = new ViewSelector(e.NewValue as string);
            if (d is ContentControl)
                ((ContentControl)d).ContentTemplateSelector = viewSelector;
            else if (d is ItemsControl)
                ((ItemsControl)d).ItemTemplateSelector = viewSelector;
            else if (d is ContentPresenter)
                ((ContentPresenter)d).ContentTemplateSelector = viewSelector;
            //else if (d is TransitionElement)
            //    ((TransitionElement)d).ContentTemplateSelector = convention;
        }

        #endregion
        public override System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item == null)
            {
                return EmptyTemplate;
            }
            Type t = item.GetType();
            string fullTypeName = item.GetType().Name;
            Debug.Assert(fullTypeName != null);
            string s = fullTypeName.Substring(0, fullTypeName.IndexOf("ViewModel"));
            if (!string.IsNullOrEmpty(Context) && Context != MAIN_CONTEXT)
            {
                s += Context;
            }
            s += "View";

            StringBuilder builder = new StringBuilder();
            builder.Append("<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:c='" + ("clr-namespace:" + t.Namespace + ";assembly=" + t.Assembly.FullName.Split(new char[] { ',' })[0]) + "'>\n");
            builder.Append("<c:" + s + ">\n");
            //builder.Append(a);
            builder.Append("</c:" + s + ">\n");
            builder.Append("</DataTemplate>");
            try
            {
                using (TextReader textReader = new StringReader(builder.ToString()))
                using (XmlReader xmlReader = new XmlTextReader(textReader))
                {
                    return XamlReader.Load(xmlReader) as DataTemplate;
                }
            }
            catch (Exception e)
            {
                Trace.Write("Unable to create DataTemplate");
            }
            return base.SelectTemplate(item, container);
        }
    }
}
